<script lang="ts" setup>
import { message } from 'ant-design-vue'
import type { IDanmu } from '../../types/api';
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
import type{ IChapter } from '../../types/api'
import vueDanmaku from 'vue3-danmaku'
import { listByEpisodeId, addDanmu } from '../../api/bulletScreen'
import { add } from '../../api/account'


// 扩展类型定义
declare module 'vue3-danmaku' {
  interface DanmakuInstance {
    resize(): void
  }
}

const { token } = $(useUser())

const { productId, episodeId, chapterList } = defineProps<{
  productId: number
  episodeId: number
  chapterList: any
}>()

const emit = defineEmits<{
  (e: 'getVideoData', value: number): void
}>()

/**
 * 弹幕逻辑
 */
 let { global } = $(useDanmuState()) // 弹幕开关
let danmakuRef = $ref<InstanceType<typeof vueDanmaku>>() // 弹幕插件
let danmuTimer: ReturnType<typeof setInterval> | null = null; // 弹幕定时器
let oVideoPlayer: HTMLVideoElement // 播放器dom
let danmuList = $ref<IDanmu[]>([]) // 弹幕列表
async function getDanmuData(push?: boolean) {
  try {
    if (!global) return;
    const currentTime = Math.floor(oVideoPlayer.currentTime);
    let response;
    if (!push) {
      // 初始弹幕
      response = await listByEpisodeId({
        productId: productId,
        episodeId: episodeId,
        endTime: currentTime + 10,
        beginTime: currentTime
      });
      danmuList = response.data;
    } else {
      // 弹幕增加
      response = await listByEpisodeId({
        productId: productId,
        episodeId: episodeId,
        endTime: currentTime + 10,
        beginTime: currentTime
      });
      if (danmakuRef) {
        response.data.map((subItem) => danmakuRef.push(subItem));
      }
    }
  } catch (error) {
    console.error('弹幕获取失败:', error);
  }
}


/**
 * 实例化播放器
 */
let speed = false
let oVideo: HTMLVideoElement // 获取video DOM
let oDanmu: HTMLDivElement // 获取弹幕 DOM
let myPlay = $ref<HTMLVideoElement | null>(null)
let init = $ref(false) // 控制弹幕展示时机
let player: ReturnType<typeof videojs> | null = null
// 获取缓存中的播放速度，否则为1
let playBackRate = $ref(process.client ? (localStorage.getItem('playBackRate') ? Number(localStorage.getItem('playBackRate')) : 1) : 1)

// 修改safeDanmuCall方法
const safeDanmuCall = (fn: Function) => {
  try {
    if (danmakuRef && oDanmu?.offsetWidth > 0) {
      requestAnimationFrame(() => fn())
    } else {
      console.warn('弹幕容器未就绪，延迟执行...')
      setTimeout(() => safeDanmuCall(fn), 300)
    }
  } catch (e) {
    console.error('弹幕操作失败:', e)
    message.error('弹幕功能暂时不可用')
  }
}

let newPlayer = async (playSrc: string) => {
  if (process.server) return
  try {
    if (!player && myPlay) {
      player = videojs(myPlay, {
        controls: true,
        fill: true,
        playbackRates: [0.5, 1, 1.25, 1.5, 1.75, 2.0],
      });
      init = true;

      // 记录 videojs 初始化成功
      console.log('videojs 初始化成功');

      player.on('play', onPlayerPlay);
      player.on('pause', onPlayerPause);

      player.on('loadedmetadata', onPlayerReady);
      player.on('ended', nextEpisod);
      player.on('seeked', onPlayerSeeked);
      player.on('fullscreenchange', () => {
        // oDanmu.style.width = `${oVideoPlayer.offsetWidth}px`;
        // oDanmu.style.height = `${oVideoPlayer.offsetHeight}px`;
        // if (danmakuRef) {
        //   danmakuRef.resize();
        // }
        requestAnimationFrame(() => {
          if (oVideoPlayer && danmakuRef) {
            oDanmu.style.width = `${oVideoPlayer.offsetWidth}px`
            oDanmu.style.height = `${oVideoPlayer.offsetHeight}px`
            danmakuRef.resize()
          }
        })
      });
      player.on('ratechange', () => {
        if (speed) {
          if (player) {
            const rate = player.playbackRate();
            if (typeof rate === 'number') {
              process.client && localStorage.setItem('playBackRate', rate.toString());
              playBackRate = rate;
            }
          }
        }
      });
    }
    speed = false;
    if (player) {
      player.src({
        src: playSrc,
        type: 'video/mp4',
      });
      // 记录设置视频源成功
      console.log('设置视频源成功');
    }
  } catch (error) {
    console.error('播放器初始化失败:', error);

  }
};



// 当播放器手动选择进度
const onPlayerSeeked = async () => {
  safeDanmuCall(async () => {
    clearInterval(danmuTimer!)
    danmuList = []
    danmakuRef?.reset()
    await getDanmuData()
    danmakuRef?.play()
    danmuTimer = setInterval(() => getDanmuData(true), 10 * 1000)
  })
}

// 当播放器暂停的时候弹幕暂停
const onPlayerPause = function () {
  if (danmuTimer) {clearInterval(danmuTimer)}
  danmakuRef?.pause()
}

// 当播放器播放时候渲染弹幕
const onPlayerPlay = function () {
  if (danmuTimer) {clearInterval(danmuTimer)}
  danmuTimer = setInterval(async () => {
    await getDanmuData(true)
  }, 10 * 1000)
  danmakuRef?.play()
}

// 当播放器好的时候初始化dom
const onPlayerReady = async () => {
  try {
    oVideo = document.querySelector('.vjs-tech')!
    oVideoPlayer = document.querySelector('#video_wrapper div video')!
    oDanmu = document.querySelector('#_danmu')!

    await getDanmuData()
    
    // DOM操作放在nextTick并添加延迟
    nextTick(() => {
      setTimeout(async () => {
        if (!oVideo || !oDanmu) return
        
        oDanmu.style.cssText = `
          width: ${oVideo.offsetWidth}px;
          height: ${oVideo.offsetHeight}px;
          top: 0;
          left: 0;
          z-index: 1000;
          position: absolute;
          pointer-events: none;
          min-width: 300px;
          min-height: 200px;
        `;

        await nextTick()
        safeDanmuCall(() => {
          danmakuRef?.resize()
          console.log('弹幕重新设置尺寸成功');
        })
      }, 300) // 添加300ms延迟
    })

    if (player) {
      player.play()
      player.playbackRate(playBackRate)
    }
    speed = true
  } catch (error) {
    console.error('播放器准备失败:', error)
  }
}

// 视频播放结束自动切换本章下一集
function nextEpisod() {
  (chapterList as IChapter[]).forEach((item) => {
    item.episodeList.forEach((subItem, subIndex) => {
      if (episodeId !== subItem.id) return
      if (subIndex + 1 < item.episodeList.length) {
        emit('getVideoData', item.episodeList[subIndex + 1].id)
      } else {
        // 跨章时暂停
      }
    })
  })
}

const { personalInfo } = $(useUser())
const { videoDanmuList, handleAddDanmu } = $(useSocket())

// 监听videoDanmuList数据变化，增加弹幕
watch(
  () => videoDanmuList.length,
  () => {
    videoDanmuList.forEach((item) => {
      if (danmakuRef) {
        danmakuRef.add(item)
      }
    })
    videoDanmuList.length = 0
  }
)

// 监听弹幕开关变量控制显示隐藏
watch(() => global, (val) => {
  if (danmakuRef) {
    try {
      val? danmakuRef.show() : danmakuRef.hide();
    } catch (error) {
      console.error('在切换弹幕显示隐藏时发生错误:', error);
    }
  }
})

// 发送弹幕
const sendDanmu = async function (danmuContent: string) {
  if (!danmuContent) {
    message.warn('请输入弹幕')
    return
  }
  const params = {
    productId: productId,
    episodeId: episodeId,
    content: danmuContent,
    playTime: oVideoPlayer.currentTime + Math.random() / 0.5
  }
  // 增加弹幕接口
  const data = await addDanmu(params, token)
  if (data.code === 0) {
    // socketio增加实时弹幕api
    handleAddDanmu({
      content: danmuContent,
      style: "COMMON_1",
      channel: 'video',
      playTime: 0,
      accountId: personalInfo.id,
      head_img: personalInfo.head_img
    })
  }
}

let timer: ReturnType<typeof setInterval> | null = null
onMounted(() => {
  oDanmu = document.querySelector('#_danmu') as HTMLDivElement;
  // 确保容器已挂载到 DOM
  if (oDanmu) {
    danmakuRef?.resize();
    console.log('danmakuRef在onMounted时重新设置尺寸');
  }

  timer = setInterval(() => {
    if (oVideoPlayer && !oVideoPlayer.paused) {
      // 上报学习时长
      add({
        productId: productId,
        episodeId: episodeId,
        duration: Math.floor(oVideoPlayer.currentTime)
      }, token)
    }
  }, 10 * 1000)
});

// 组件即将销毁时删除播放器、弹幕轮询、上报时长轮询
onBeforeUnmount(() => {
  if (player) player.dispose()
  if (danmuTimer) {clearInterval(danmuTimer)}
  if (timer) clearInterval(timer)
})

defineExpose({ newPlayer, sendDanmu })


</script>

<template>
  <Teleport v-if="init" to=".video-js">
    <div id="_danmu" style="display: contents">
      <vueDanmaku style="width: 100%; height: 100%" ref="danmakuRef" v-model:danmus="danmuList" :channels="5"
        :autoplay="false" :speeds="160" useSlot>
        <template v-slot:dm="{ danmu }">
          <div flex items-center>
            <img :src="danmu.head_img" wh-25 rounded-full />
            <span class="TEXT" :class="danmu.style">{{ danmu.content }}</span>
          </div>
        </template>
      </vueDanmaku>
    </div>
  </Teleport>
  <video ref="myPlay" controls style="height: 100%; width: 100%"
    class="video-js vjs-default-skin vjs-big-play-centered" />
</template>


<style scoped>
.TEXT {
  font-size: 24px;
  font-weight: bold;
  color: transparent;
  background-clip: text;
}

.PLANT {
  color: white;
  -webkit-text-stroke: 2px black;
}

.COMMON_1 {
  background-image: linear-gradient(90deg, #fdb34b 0%, #fbe36c 98.57142857142858%);
}

.COMMON_2 {
  background-image: linear-gradient(90deg, #5094ea 0%, #5d41ba 45.34285714285714%, #c669a0 98.57142857142858%);
}

.COMMON_3 {
  background-image: linear-gradient(90deg, #fdb34b 0%, #fbe36c 98.57142857142858%);
}

.COMMON_4 {
  background-image: linear-gradient(90deg, #5094ea 0%, #5d41ba 45.34285714285714%, #c669a0 98.57142857142858%);
}

.COMMON_5 {
  background-image: linear-gradient(90deg, #fe4d5f 0%, #ffc666 98.57142857142858%);
}

.VIP_1 {
  background-image: linear-gradient(90deg, #785cc8 0%, #854edb 98.57142857142858%);
}

.VIP_2 {
  background-image: linear-gradient(90deg, #254abd 0%, #7dabef 98.57142857142858%);
}

.VIP_3 {
  background-image: linear-gradient(90deg, #cf45e7 0%, #d967e3 98.57142857142858%);
}

.VIP_4 {
  background-image: linear-gradient(90deg, #fdb34b 0%, #fbe36c 98.57142857142858%);
}

.VIP_5 {
  background-image: linear-gradient(90deg, #785cc8 0%, #854edb 98.57142857142858%);
}

.VIP_TRAIN_1 {
  background-image: linear-gradient(90deg, #fcb64f 0%, #ffb105 98.57142857142858%);
}

.VIP_TRAIN_2 {
  background-image: linear-gradient(0deg, #bb4444 0%, #f66d68 90.81349206349216%);
}

.TRAIN_1 {
  background-image: linear-gradient(-180deg, #ecc27d 9.186507936507835%, #b76420 100%);
}

.TRAIN_2 {
  background-image: linear-gradient(-180deg, #2e6ec4 9.186507936507835%, #4252c4 100%);
}
</style>